import { user_attribute } from '@src/db/src/models/user/user_attribute'
import { user_equipment } from '@src/db/src/models/user/user_equipment'
import { equipment_list } from '@src/db/src/models/item/equipment_list'

/**
 * 根据基础属性和装备属性计算衍生属性并更新
 * @param uid 用户uid
 */
export async function updateUserAttributes(uid: number): Promise<void> {
  // 读取用户属性
  const attr = await user_attribute.findOneValue({ where: { uid } })
  if (!attr) return

  // 基础属性
  const {
    constitution_base,
    spirit_base,
    strength_base,
    intelligence_base,
    agility_base,
    perception_base,
    charm_base,
    luck_base
  } = attr

  // 初始化装备加成
  let constitution_equip = 0
  let spirit_equip = 0
  let strength_equip = 0
  let intelligence_equip = 0
  let agility_equip = 0
  let perception_equip = 0
  let charm_equip = 0
  let luck_equip = 0

  let hp_max_equip = 0
  let mp_max_equip = 0
  let atk_equip = 0
  let matk_equip = 0
  let def_equip = 0
  let mdef_equip = 0
  let hit_equip = 0
  let dodge_equip = 0
  let crit_equip = 0
  let crit_dmg_equip = 0
  let crit_avoid_equip = 0
  let crit_resist_equip = 0
  let speed_equip = 0
  let tenacity_equip = 0
  let hp_recover_equip = 0
  let mp_recover_equip = 0

  // 读取装备
  const equip = await user_equipment.findOneValue({ where: { uid } })
  if (equip) {
    const slots = [
      'weapon',
      'sub_weapon',
      'shoulder',
      'upper',
      'waist',
      'lower',
      'foot',
      'bracelet',
      'ring',
      'necklace'
    ]
    for (const slot of slots) {
      const equipName = equip[slot]
      if (equipName) {
        const eq = await equipment_list.findOneValue({
          where: { name: equipName }
        })
        if (eq) {
          constitution_equip += eq.constitution || 0
          spirit_equip += eq.spirit || 0
          strength_equip += eq.strength || 0
          intelligence_equip += eq.intelligence || 0
          agility_equip += eq.agility || 0
          perception_equip += eq.perception || 0
          charm_equip += eq.charm || 0
          luck_equip += eq.luck || 0

          hp_max_equip += eq.hp_max || 0
          mp_max_equip += eq.mp_max || 0
          atk_equip += eq.atk || 0
          matk_equip += eq.matk || 0
          def_equip += eq.def || 0
          mdef_equip += eq.mdef || 0
          hit_equip += eq.hit || 0
          dodge_equip += eq.dodge || 0
          crit_equip += eq.crit || 0
          crit_dmg_equip += eq.crit_dmg || 0
          crit_avoid_equip += eq.crit_avoid || 0
          crit_resist_equip += eq.crit_resist || 0
          speed_equip += eq.speed || 0
          tenacity_equip += eq.tenacity || 0
          hp_recover_equip += eq.hp_recover || 0
          mp_recover_equip += eq.mp_recover || 0
        }
      }
    }
  }

  // 计算最终属性
  const constitution_final = constitution_base + constitution_equip
  const spirit_final = spirit_base + spirit_equip
  const strength_final = strength_base + strength_equip
  const intelligence_final = intelligence_base + intelligence_equip
  const agility_final = agility_base + agility_equip
  const perception_final = perception_base + perception_equip
  const charm_final = charm_base + charm_equip
  const luck_final = luck_base + luck_equip

  // 属性系数计算
  const constitution_segment = segmentedCoef(constitution_final)
  const spirit_segment = segmentedCoef(spirit_final)
  const strength_segment = segmentedCoef(strength_final)
  const intelligence_segment = segmentedCoef(intelligence_final)
  const agility_segment = segmentedCoef(agility_final)
  const perception_segment = segmentedCoef(perception_final)
  const charm_segment = segmentedCoef(charm_final)
  const luck_segment = segmentedCoef(luck_final)

  const hp_max =
    (hp_max_equip + constitution_final * 5) * (1 + constitution_segment)
  const mp_max = (mp_max_equip + spirit_final * 5) * (1 + spirit_segment)
  const atk = (atk_equip + strength_final * 1) * (1 + strength_segment)
  const matk =
    (matk_equip + intelligence_final * 1) * (1 + intelligence_segment)
  const def =
    (def_equip + constitution_final * 1) *
    (1 + constitution_segment * 0.75 + strength_segment * 0.25)
  const mdef =
    (mdef_equip + spirit_final * 1) *
    (1 + spirit_segment * 0.75 + intelligence_segment * 0.25)
  const hit =
    (hit_equip +
      agility_final * 2 +
      strength_final * 1 +
      intelligence_final * 1 +
      luck_final * 10) *
    (1 + agility_segment + luck_segment)
  const dodge =
    (dodge_equip + agility_final * 2 + luck_final * 10) *
    (1 + agility_segment + luck_segment)
  const crit =
    (crit_equip + strength_final * 4 + luck_final * 10) *
    (1 + agility_segment * 0.25 + perception_segment * 0.75 + luck_segment)
  const crit_dmg =
    (crit_dmg_equip + intelligence_final * 4 + luck_final * 10) *
    (1 + agility_segment * 0.25 + perception_segment * 0.75 + luck_segment)
  const crit_avoid =
    (crit_avoid_equip + constitution_final * 1 + spirit_final * 1) *
    (1 + perception_segment * 0.5 + spirit_segment * 0.5)
  const crit_resist =
    (crit_resist_equip + constitution_final * 1 + spirit_final * 1) *
    (1 + constitution_segment * 0.5 + perception_segment * 0.5)
  const speed = (speed_equip + agility_final * 4) * (1 + agility_segment)
  const tenacity =
    (tenacity_equip + constitution_final * 1 + spirit_final * 1) *
    (1 + constitution_segment * 0.5 + spirit_segment * 0.5)
  const hp_recover =
    (hp_recover_equip + constitution_final * 1) * (1 + constitution_segment)
  const mp_recover =
    (mp_recover_equip + spirit_final * 1) * (1 + spirit_segment)

  // 更新数据
  await user_attribute.update(
    {
      constitution_final,
      spirit_final,
      strength_final,
      intelligence_final,
      agility_final,
      perception_final,
      charm_final,
      luck_final,
      hp_max,
      mp_max,
      atk,
      matk,
      def,
      mdef,
      hit,
      dodge,
      crit,
      crit_dmg,
      crit_avoid,
      crit_resist,
      speed,
      tenacity,
      hp_recover,
      mp_recover
    },
    { where: { uid } }
  )
}

// 分段系数计算函数
export function segmentedCoef(value: number): number {
  let total = 0
  let remain = value
  let coef = 1
  let step = 10

  while (remain > 0) {
    const part = Math.min(remain, step)
    total += part * coef
    remain -= part
    coef *= 0.9
  }
  return total * 0.01
}

/**
 * 读取用户属性表中的指定字段
 * @param uid 用户uid
 * @param fieldName 要读取的字段名
 * @returns Promise<number | string | null> 字段值，未找到返回null
 */
export async function readUserAttribute(
  uid: number,
  fieldName: string
): Promise<number | string | null> {
  const attr = await user_attribute.findOneValue({ where: { uid } })
  if (!attr) throw new Error('用户不存在')

  if (!(fieldName in attr)) throw new Error('字段不存在')

  return attr[fieldName] ?? null
}

/**
 * 写入用户属性表中的指定字段
 * @param uid 用户uid
 * @param fieldName 要修改的字段名
 * @param newValue 修改后的数值
 * @returns Promise<boolean> 修改成功返回true，失败抛异常
 */
export async function writeUserAttribute(
  uid: number,
  fieldName: string,
  newValue: number | string
): Promise<boolean> {
  // 检查该字段是否存在
  const attr = await user_attribute.findOne({ where: { uid } })
  if (!attr) throw new Error('用户不存在')

  if (!(fieldName in attr)) throw new Error('字段不存在')

  // 执行更新
  await user_attribute.update({ [fieldName]: newValue }, { where: { uid } })
  return true
}
